﻿using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace eLoan.Models
{
    public static class AdministrationHelper
    {
        #region constants

        public const string StyleHidden = "display:none;";
        public const string StyleShownBlock = "display:block;";
        public const string StyleShownInline = "display:in-line;";
        public const string StyleDisabled = "disabled: disabled";
        public const string strScheduledDates = "scheduledDates";
        public const string strChargeTypes = "chargeTypes";
        public const string strBranches = "branches";
        public const string strAgents = "agents";
        public const string strBorrowers = "borrowers";
        public const string strProceedTypes = "proceedTypes";
        public const string strPaymentTpes = "paymentTypes";

        #endregion

        #region enums

        public enum DBCommand
        {
            Add = 0,
            Edit = 1,
            Delete = 2,
            Cancel = 3,
            CreateSchedule = 4,
            DeleteSchedule = 5,
            ReleaseCheque = 6,
            Save = 7,
            CloseDocument = 8,
            Refresh = 9,
            Export = 10,
            ExportSummary = 11,
            Post = 12,
            Void = 13,
            SaveDelayed = 14,
            SaveDelinquent = 15,
            SendNotification = 16,
            ExportToExcel = 17,
            ExportDaily = 18,
            ExportOthers = 19,
            SaveDaily = 20,
            SaveOthers = 21,
            Dishonor = 22,
            Clear = 23,
            ExportToPdf = 24
        }

        public enum ProceedType
        {
            None = 0,
            Daily = 1,
            Weekly = 2,
            SemiMonthly = 3,
            Monthly = 4
        }

        public enum LoanStatus 
        {
            None = 0,
            New = 1,
            ReleasedToBranch = 2,
            ReleasedToBorrower = 3,
            Closed = 4,
            Cancelled = 5,
            RequestClose = 6
        }

        public enum LoanPaymentStatus
        {
            None = 0,
            New = 1,
            Posted = 2,
            ForClearing = 3,
            Cleared = 4,
            Dishonored = 5,
            Cancelled = 6
        }

        public enum Role
        {
            None = 0,
            Admin = 1,
            User = 2
        }

        public enum UserPageAccess
        { 
            None = 0,
            Users = 1,
            Branches = 2,
            Agents = 3,
            LoanTypes = 4,
            ChargeTypes = 5,
            PaymentTypes = 6,
            AddressBook = 7,
            Loans = 8,
            CancelLoan = 9,
            PrintCheque = 10,
            PrintContract = 11,
            ReleaseToBranch = 12,
            ReleaseToCustomer = 13,
            LoanPayment = 14,
            LoanPenalty = 15,
            VoidLoanPayment = 16,
            CloseLoan = 17,
            AgentItinerary = 18,
            CollectionReport = 19,
            SalesReport = 20,
            ChequeReport = 21,
            SavingsReport = 22,
            StatementOfAccount = 23,
            PenaltyHistory = 24,
            ClosedLoansReport = 25,
            Notifications = 26,
            LoanNotification = 27,
            RequestCloseLoan = 28,
            Prospects = 29,
            DuePayments = 30,
            DailyCollectionReconciliation = 31,
            DailyCollectionReconciliationReport = 32,
            Banks = 33,
            ChequeClearing = 34,
            AgingReport = 35
        }

        //public enum Notification
        //{
        //    Delayed = 1,
        //    Delinquent = 2,
        //    Renewal = 3
        //}

        public enum ChargeTypeSort
        {
            Finance = 1,
            NonFinance = 2
        }

        public enum PenaltySort
        {
            Penalty = 1,
            Delayed = 2,
            Delinquent = 3
        }

        public enum CollectionReconciliationStatus
        {
            New = 1,
            Reviewed = 2
        }

        public enum PaymentType
        {
            None = 0,
            CashR = 1,
            ChequeR =2,
            CashN = 3,
            ChequeN = 4,
            FundTransfer = 5
        }

        #endregion

        #region MasterfileDropDowns

        public static IEnumerable<SelectListItem> GetAgentDropDownList(IEnumerable<Agent> agents)
        {
            return agents.Where(w => w.IsActive == true).Select(s => new SelectListItem { Value = s.ID.ToString(), Text = s.AgentName });
        }

        public static IEnumerable<SelectListItem> GetBorrowerDropDownList(IEnumerable<Borrower> borrowers)
        {
            return borrowers.Where(w => w.IsActive == true).Select(s => new SelectListItem { Value = s.ID.ToString(), Text = s.BorrowerName });
        }

        public static IEnumerable<SelectListItem> GetBranchDropDownList(IEnumerable<Branch> branches)
        {
            return branches.Where(w => w.IsActive == true).Select(s => new SelectListItem { Value = s.BranchCode.ToString(), Text = s.BranchName });
        }

        public static IEnumerable<SelectListItem> GetNotificationDropDownList(IEnumerable<Notification> notifications)
        {
            return notifications.Where(w => w.IsActive == true).Select(s => new SelectListItem { Value = s.ID.ToString(), Text = s.NotificationName });
        }

        public static IEnumerable<SelectListItem> GetBranchDropDownListByUserRole(DatabaseContext db, string userName)
        {
            List<Branch> branches;
            var loggedInUserRoleID = AdministrationHelper.GetLoggedInUserRoleID(db, userName);
            var loggedInUserBranchCode = GetLoggedInUserBranchCode(db, userName);
            if (loggedInUserRoleID == (int)AdministrationHelper.Role.Admin)
            {
                branches = db.Branches.ToList();
            }
            else
            {
                branches = db.Branches.Where(w => w.BranchCode == loggedInUserBranchCode).ToList();
            }

            return GetBranchDropDownList(branches);
        }

        public static IEnumerable<SelectListItem> GetChargeTypeDropDownList(IEnumerable<ChargeType> chargeTypes)
        {
            return chargeTypes.Where(w => w.IsActive == true).Select(s => new SelectListItem { Value = s.ID.ToString(), Text = s.ChargeTypeName });
        }

        public static IEnumerable<SelectListItem> GetLoanTypeDropDownList(IEnumerable<LoanType> loanTypes)
        {
            return loanTypes.Where(w => w.IsActive == true).Select(s => new SelectListItem { Value = s.ID.ToString(), Text = s.LoanTypeName });
        }

        public static IEnumerable<SelectListItem> GetPaymentTypeDropDownList(IEnumerable<eLoan.Models.PaymentType> paymentTypes)
        {
            var list = paymentTypes.Where(w => w.IsActive == true).Select(s => new SelectListItem { Value = s.ID.ToString(), Text = s.PaymentTypeName });
            return list;
        }

        public static IEnumerable<SelectListItem> GetProceedTypeDropDownList()
        {
            var proceedTypes = new List<SelectListItem>();

            proceedTypes.Add(new SelectListItem { Value = ((int)ProceedType.Daily).ToString(), Text = ProceedType.Daily.ToString() });
            proceedTypes.Add(new SelectListItem { Value = ((int)ProceedType.Weekly).ToString(), Text = ProceedType.Weekly.ToString() });
            proceedTypes.Add(new SelectListItem { Value = ((int)ProceedType.SemiMonthly).ToString(), Text = ProceedType.SemiMonthly.ToString() });
            proceedTypes.Add(new SelectListItem { Value = ((int)ProceedType.Monthly).ToString(), Text = ProceedType.Monthly.ToString() });

            return proceedTypes;
        }

        public static IEnumerable<SelectListItem> GetRoleDropDownList()
        {
            var roles = new List<SelectListItem>();

            roles.Add(new SelectListItem { Value = ((int)Role.Admin).ToString(), Text = Role.Admin.ToString() });
            roles.Add(new SelectListItem { Value = ((int)Role.User).ToString(), Text = Role.User.ToString() });
            
            return roles;
        }

        public static IEnumerable<SelectListItem> GetLoanStatusDropDownList()
        {
            var list = new List<SelectListItem>();

            list.Add(new SelectListItem { Value = ((int)LoanStatus.None).ToString(), Text = LoanStatus.None.ToString() });
            list.Add(new SelectListItem { Value = ((int)LoanStatus.New).ToString(), Text = LoanStatus.New.ToString() });
            list.Add(new SelectListItem { Value = ((int)LoanStatus.ReleasedToBranch).ToString(), Text = "Released To Branch" });
            list.Add(new SelectListItem { Value = ((int)LoanStatus.ReleasedToBorrower).ToString(), Text = "Released To Borrower" });
            list.Add(new SelectListItem { Value = ((int)LoanStatus.Closed).ToString(), Text = LoanStatus.Closed.ToString() });
            list.Add(new SelectListItem { Value = ((int)LoanStatus.Cancelled).ToString(), Text = LoanStatus.Cancelled.ToString() });

            return list;
        }

        public static IEnumerable<SelectListItem> GetAgingDayList()
        {
            var list = new List<SelectListItem>();

            list.Add(new SelectListItem { Value = "0", Text = "Custom Date Range" });
            list.Add(new SelectListItem { Value = "30", Text = "Last 30 Days" });
            list.Add(new SelectListItem { Value = "60", Text = "Last 60 Days" });
            list.Add(new SelectListItem { Value = "90", Text = "Last 90 Days" });
            
            return list;
        }

        public static IEnumerable<SelectListItem> GetUserProfiles()
        {
            return new DatabaseContext().UserProfiles.ToList().Select(s => new SelectListItem { Value = s.UserId.ToString(), Text = s.UserName });
        }

        public static IEnumerable<SelectListItem> GetBanks()
        {
            var list = new DatabaseContext().Banks.ToList().Select(s => new SelectListItem { Value = s.ID.ToString(), Text = s.BankName }).ToList();
            list.Insert(0, new SelectListItem { Value = "0", Text = "" });

            return list;
        }

        #endregion

        #region ForeignKeyNames

        public static string GetAgentName(int agentID)
        {
            using (var db = new DatabaseContext())
            {
                var agent = db.Agents.Where(w => w.ID == agentID);
                if (agent.Any())
                    return agent.SingleOrDefault<Agent>().AgentName;
                else
                    return string.Empty;
            }
        }

        public static string GetBorrowerName(int borrowerID)
        {
            using (var db = new DatabaseContext())
            {
                var borrower = db.Borrowers.Where(w => w.ID == borrowerID);
                if (borrower.Any())
                    return borrower.SingleOrDefault<Borrower>().BorrowerName;
                else
                    return string.Empty;
            }
        }

        public static string GetBorrowerContactNumbers(int borrowerID)
        {
            using (var db = new DatabaseContext())
            {
                var borrower = db.Borrowers.Where(w => w.ID == borrowerID);
                if (borrower.Any())
                    return borrower.SingleOrDefault<Borrower>().ContactNumbers;
                else
                    return string.Empty;
            }
        }

        public static string GetBorrowerAddress(int borrowerID)
        {
            using (var db = new DatabaseContext())
            {
                var borrower = db.Borrowers.Where(w => w.ID == borrowerID);
                if (borrower.Any())
                    return borrower.SingleOrDefault<Borrower>().Address;
                else
                    return string.Empty;
            }
        }

        public static string GetBranchName(string branchCode)
        {
            using (var db = new DatabaseContext())
            {
                var branch = db.Branches.Where(w => w.BranchCode == branchCode);
                if (branch.Any())
                    return branch.SingleOrDefault<Branch>().BranchName;
                else
                    return string.Empty;
            }
        }

        public static string GetChargeTypeName(int chargeTypeID)
        {
            using (var db = new DatabaseContext())
            {
                var chargeType = db.ChargeTypes.Where(w => w.ID == chargeTypeID);
                if (chargeType.Any())
                    return chargeType.SingleOrDefault<ChargeType>().ChargeTypeName;
                else
                    return string.Empty;
            }
        }

        public static string GetProceedTypeName(int proceedTypeID)
        {
            switch (proceedTypeID)
            {
                case 1: return ProceedType.Daily.ToString();
                case 2: return ProceedType.Weekly.ToString();
                case 3: return ProceedType.SemiMonthly.ToString();
                case 4: return ProceedType.Monthly.ToString();
                default: return ProceedType.None.ToString();
            }
        }

        public static string GetLoanTypeName(int loanTypeID)
        {
            var loanTypes = new DatabaseContext().LoanTypes.Where(w => w.ID == loanTypeID && w.IsActive == true);
            if (loanTypes.Any())
                return loanTypes.SingleOrDefault<LoanType>().LoanTypeName;
            else
                return string.Empty;
        }

        public static string GetPaymentTypeName(int paymentTypeID)
        {
            var paymentTypes = new DatabaseContext().PaymentTypes.Where(w => w.ID == paymentTypeID && w.IsActive == true);
            if (paymentTypes.Any())
                return paymentTypes.SingleOrDefault<eLoan.Models.PaymentType>().PaymentTypeName;
            else
                return string.Empty;
        }

        public static string GetLoanStatusName(int statusID)
        {
            switch (statusID)
            {
                case 1: return LoanStatus.New.ToString();
                case 2: return LoanStatus.ReleasedToBranch.ToString();
                case 3: return LoanStatus.ReleasedToBorrower.ToString();
                case 4: return LoanStatus.Closed.ToString();
                default: return LoanStatus.None.ToString();
            }
        }

        public static string GetLoanPaymentStatus(int paymentStatusID)
        {
            switch(paymentStatusID)
            {
                case 1: return LoanPaymentStatus.New.ToString();
                case 2: return LoanPaymentStatus.Posted.ToString();
                default: return LoanPaymentStatus.None.ToString();
            }
        }

        public static string LoanTypeName(int loanTypeID)
        {
            var loanType = new DatabaseContext().LoanTypes.Where(w => w.ID == loanTypeID && w.IsActive == true);
            if (loanType.Any())
                return loanType.SingleOrDefault<LoanType>().LoanTypeName;
            else
                return string.Empty;
        }

        public static string GetRoleName(int roleID)
        {
            switch (roleID)
            {
                case 1: return Role.Admin.ToString();
                case 2: return Role.User.ToString();
                default: return Role.None.ToString();
            }
        }

        #endregion

        #region Master Information

        #region Models

        public static AgentModel GetAgentModel(DatabaseContext db, int agentID)
        {
            var agentModel = new AgentModel();
            var agent = db.Agents.Where(w => w.ID == agentID);
            var branches = db.Branches;

            agentModel.Branches = GetBranchDropDownList(branches);
                
            if (agent.Any())
            {
                agentModel.Agent = agent.SingleOrDefault<Agent>();
                var branch = branches.Where(w => w.BranchCode == agentModel.Agent.BranchCode);

                if (branch.Any())
                    agentModel.BranchName = branch.SingleOrDefault<Branch>().BranchName;
                else
                    agentModel.BranchName = string.Empty;
                    
            }
            

            return agentModel;
        }

        public static IEnumerable<AgentModel> GetAgentModels(IEnumerable<Agent> agents)
        {
            var db = new DatabaseContext();
            var agentModels = new List<AgentModel>();

            foreach (var agent in agents)
            {
                var agentModel = new AgentModel();
                agentModel = GetAgentModel(db, agent.ID);

                agentModels.Add(agentModel);
            }

            return agentModels;
        }

        public static UserModel GetUserModel(DatabaseContext db, int userID)
        {
            var userModel = new UserModel();
            var user = db.Users.Where(w => w.ID == userID);
            var branches = db.Branches;
            
            userModel.Branches = GetBranchDropDownList(branches);
            userModel.Roles = GetRoleDropDownList();

            if (user.Any())
            {
                userModel.User = user.SingleOrDefault<User>();

                var branch = branches.Where(w => w.BranchCode == userModel.User.BranchCode);
                if (branch.Any())
                    userModel.BranchName = branch.SingleOrDefault<Branch>().BranchName;
                else
                    userModel.BranchName = string.Empty;

                userModel.RoleName = GetRoleName(userModel.User.RoleID);
            }


            return userModel;
        }

        public static IEnumerable<UserModel> GetUserModels(List<User> users)
        {
            var db = new DatabaseContext();
            var userModels = new List<UserModel>();

            foreach (var user in users)
            {
                var userModel = new UserModel();
                userModel = GetUserModel(db, user.ID);

                userModels.Add(userModel);
            }

            return userModels;
        }

        public static UserAccessModel GetUserAccess(DatabaseContext db, string userName)
        {
            var access = db.UserPageAccess.Where(w => w.UserName == userName);
            var userAccess = new UserAccessModel();

            // Administration access
            userAccess.HasUsersAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.Users);
            userAccess.HasBanksAccess= access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.Banks);
            userAccess.HasBranchesAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.Branches);
            userAccess.HasAgentsAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.Agents);
            userAccess.HasLoanTypesAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.LoanTypes);
            userAccess.HasChargeTypesAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.ChargeTypes);
            userAccess.HasPaymentTypesAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.PaymentTypes);
            userAccess.HasNotificationsAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.Notifications);
            userAccess.HasAdministrationAccess = userAccess.HasUsersAccess
                                                || userAccess.HasBanksAccess
                                                || userAccess.HasBranchesAccess
                                                || userAccess.HasAgentsAccess
                                                || userAccess.HasLoanTypesAccess
                                                || userAccess.HasChargeTypesAccess
                                                || userAccess.HasNotificationsAccess
                                                || userAccess.HasPaymentTypesAccess;

            // Masterfile access
            userAccess.HasAddressBookAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.AddressBook);
            userAccess.HasProspectsAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.Prospects);
            userAccess.HasMasterFilesAccess = userAccess.HasAddressBookAccess
                                                || userAccess.HasProspectsAccess;

            // Fundings access
            userAccess.HasLoansAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.Loans);
            userAccess.HasCancelLoanAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.CancelLoan);
            userAccess.HasPrintChequeAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.PrintCheque);
            userAccess.HasPrintContractAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.PrintContract);
            userAccess.HasReleaseToBranchAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.ReleaseToBranch);
            userAccess.HasReleaseToCustomerAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.ReleaseToCustomer);
            userAccess.HasFundingsAccess = userAccess.HasLoansAccess
                                            || userAccess.HasCancelLoanAccess
                                            || userAccess.HasPrintChequeAccess
                                            || userAccess.HasPrintContractAccess
                                            || userAccess.HasReleaseToBranchAccess
                                            || userAccess.HasReleaseToCustomerAccess;
            

            // Workspace
            userAccess.HasLoanPaymentAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.LoanPayment);
            userAccess.HasChequeClearingAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.ChequeClearing);
            userAccess.HasLoanPenaltyAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.LoanPenalty);
            userAccess.HasVoidLoanPaymentAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.VoidLoanPayment);
            userAccess.HasRequestCloseLoanAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.RequestCloseLoan);
            userAccess.HasCloseLoanAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.CloseLoan);
            userAccess.HasLoanNotificationAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.LoanNotification);
            userAccess.HasDailyCollectionReconciliationAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.DailyCollectionReconciliation);
            userAccess.HasWorkspaceAccess = userAccess.HasLoanPaymentAccess
                                        || userAccess.HasLoanPenaltyAccess
                                        || userAccess.HasVoidLoanPaymentAccess
                                        || userAccess.HasRequestCloseLoanAccess
                                        || userAccess.HasCloseLoanAccess
                                        || userAccess.HasDailyCollectionReconciliationAccess
                                        || userAccess.HasLoanNotificationAccess
                                        || userAccess.HasChequeClearingAccess;
                                        

            // Reports access
            userAccess.HasAgentItineraryAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.AgentItinerary);
            userAccess.HasCollectionReportAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.CollectionReport);
            userAccess.HasSalesReportAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.SalesReport);
            userAccess.HasChequeReportAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.ChequeReport);
            userAccess.HasSavingsReportAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.SavingsReport);
            userAccess.HasSOAAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.StatementOfAccount);
            userAccess.HasPenaltyHistoryAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.PenaltyHistory);
            userAccess.HasClosedLoansReportAccess= access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.ClosedLoansReport);
            userAccess.HasDuePaymentsAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.DuePayments);
            userAccess.HasDailyCollectionReconciliationReportAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.DailyCollectionReconciliationReport);
            userAccess.HasAgingReportAccess = access.Any(a => a.PageID == (int)AdministrationHelper.UserPageAccess.AgingReport);
            userAccess.HasReportsAccess = userAccess.HasAgentItineraryAccess
                                        || userAccess.HasCollectionReportAccess
                                        || userAccess.HasSalesReportAccess
                                        || userAccess.HasChequeReportAccess
                                        || userAccess.HasSavingsReportAccess
                                        || userAccess.HasSOAAccess
                                        || userAccess.HasPenaltyHistoryAccess
                                        || userAccess.HasClosedLoansReportAccess
                                        || userAccess.HasDailyCollectionReconciliationReportAccess
                                        || userAccess.HasDuePaymentsAccess
                                        || userAccess.HasAgingReportAccess;
            return userAccess;
        }

        public static string GetLoggedInUserBranchCode(DatabaseContext db, string userName)
        {
            var branchCode = string.Empty;

            var user = db.Users.Where(w => w.UserName == userName);
            if (user.Any())
                branchCode = user.SingleOrDefault<User>().BranchCode;

            return branchCode;
        }

        public static int GetLoggedInUserRoleID(DatabaseContext db, string userName)
        {
            var roleID = 0;

            var user = db.Users.Where(w => w.UserName == userName);
            if (user.Any())
                roleID = user.SingleOrDefault<User>().RoleID;

            return roleID;
        }

        #endregion

        #endregion

    }

}